#ifndef SUPERHEADER_H
#define SUPERHEADER_H

#include <iostream>
#include <math.h>
#include <fstream>

#include <QString>
#include <QFile>
#include <QDebug>
#include <QPointF>
#include <qmath.h>

using namespace std;

// количество потоков, каналов и узлов в сети
const int numberOfFlows    = 14;
const int numberOfHubs     = 12;
const int numberOfChannels = 11;

/*
  Натуральный логарифм
*/
inline double ln(double num) {
  return log(num);
}

/*
  Датчик псевдослучайных чисел (0.0, 1.0)
  постусловие: результат в допустимых пределах
*/
inline double ran() {
  double res = qrand() % RAND_MAX;
  if (!res) ++res;
  res /= (double)RAND_MAX;

  if (res >= 1.0 || res <= 0.0) {
    qFatal("error in ran(): выдает числа за пределами интервала (0.0, 1.0).");
  }

  return res;
}

/*
  Преобразование интенсивности во время и средней длины сообщения в размер сообщения
*/
inline double conversion(double val) {
  return ln( 1.0 / ran() )  /  val;
}

/*
  Структура входных данных задачи
*/
struct InputData {
  int    limitMessages;  // число сообщений для анализа сети
  double capacity;       // пропускная способность для каналов
  double intensity;      // интенсивность для потоков
  double messageLength;  // средняя длина сообщения для потоков
  int    controlledFlow; // номер контролируемого потока

  InputData() :
    limitMessages(1000),
    capacity(1.0),
    intensity(0.0001),
    messageLength(1.0),
    controlledFlow(0) { }
};

/*
  Структура параметров сети
*/
struct NetworkSettings {
  double          timeChannelSwitching;       // время коммутации каналов
  double          timeMessageSwitching;       // время коммутации сообщений
  double          timePacketSwitching;        // время коммутации пакетов
  double          currentTime;                // текущее время
  QVector<double> timeOfReleaseChannels;      // время освобождения каналов
  QVector<double> tempTimeOfReleaseChannels;  // время окончания передачи сообщений
  QVector<double> timeMessages;               // время появления сообщений
  QVector<double> sizeOfMessages;             // размер сообщений
  double          maxPacketSize;              // максимальный размер пакета
  QVector<int>    numberOfPackets;            // число пакетов в сообщениях
  QVector<int>    numberOfTransferredPackets; // число переданных пакетов сообщений
  QVector<double> timeTransmissionOfPackets;  // время передачи пакетов

  NetworkSettings() :
    timePacketSwitching(0.0),
    currentTime(0.0),
    maxPacketSize(0.01) { }

  /*
    Инициализация параметров сети
  */
  void init(InputData inputData)
  {
    timeChannelSwitching = maxPacketSize / inputData.capacity;
    timeMessageSwitching = 0.1 * (maxPacketSize / inputData.capacity);
    timePacketSwitching  = timeMessageSwitching;
    currentTime          = 0.0;
    timeOfReleaseChannels.fill(0.0, numberOfChannels);

    tempTimeOfReleaseChannels = timeOfReleaseChannels;

    numberOfPackets.fill(-1, numberOfFlows);
    numberOfTransferredPackets.fill(1, numberOfFlows);

    timeTransmissionOfPackets.fill(-1.0, numberOfFlows);

    for (int i = 0; i < numberOfFlows; ++i) {
      timeMessages.push_back( conversion(inputData.intensity) );
      sizeOfMessages.push_back( conversion(inputData.messageLength) );
    }
  }
};

InputData       inputData;       // структура входных данных задачи
NetworkSettings networkSettings; // структура параметров сети

#endif
